import { AES, enc } from 'crypto-js'
import { isType, runtime } from './UtilityBox';
import { UtilString } from './UtilString';

type encryptionData = String | Object;

type EncryptType = {
  encrypt: string
  encryptEnhance?: string
  encryptASCII?: Array<number>
};
interface decryptionDataType {
  decryption?: string,
  decryptionEnhance?: string,
  decryptionASCII?: string
}

type decryptionType = "ASCII" | "Decryption" | "DecryptionEnhance" | "All"

/**
 * 原生加密，不使用任何第三方库，兼容浏览器和JavaScript runTime
 */
export class NativeEncrypt extends UtilString {
  /**
   * 数据类型转化
   * @param setObj 
   * @returns String and Object
   */
  static objectSwitchString = (setObj: Object | string): object | string => {
    if (isType(setObj) !== 'Object') return setObj;
    return JSON.stringify(setObj);
  }

  /**
   * 字符串编码为 Base64 
   * @param data 编码字符串内容 string | Object
   * @returns Base64 String
   */
  static StringToBase64 = (data: string | Object): string => {
    let set = encodeURIComponent(NativeEncrypt.objectSwitchString(data) as string), result = btoa(set)
    return result
  }

  /**
   * Base64转译为字符串
   * @param data base64字符串
   * @returns string
   */
  static Base64ToString = (data: string) => {
    let jieMi = atob(data), jieM = decodeURIComponent(jieMi);
    return jieM;
  }


  /**
   * 数据加密
   * @param data 数据源
   * @returns 加密后的数据
   */
  static encryptTobase64 = (data: any): EncryptType => {
    if (isType(data) === 'Object') {
      const result = NativeEncrypt.StringToBase64(data)
      return {
        encrypt: result,
        encryptASCII: this.TextToASCII(result, result.length),
        encryptEnhance: btoa(this.TextToASCII(result, result.length) as unknown as string),
      }
    } else {
      const set = NativeEncrypt.StringToBase64(data)
      return {
        encrypt: set,
        encryptEnhance: btoa(this.TextToASCII(set, set.length) as unknown as string),
        encryptASCII: this.TextToASCII(set, set.length)
      }
    }
  }

  /**
   * 解码数据
   * @param data EncryptType
   * @param type "ASCII" => 对应 encryptASCII | "Decryption" => 对应 encrypt| "DecryptionEnhance" => 对应 DecryptionEnhance | "All" 为默认，包含所有
   * @returns 
   */
  static decryptionWithBase64 = (data: EncryptType, type: decryptionType = 'All'): Map<string, object | string | number> => {
    try {
      let decryptionMap: Map<string, object | string | number> = new Map();

      const { encrypt, encryptASCII, encryptEnhance } = data;

      let decryption, decryptionASCII, decryptionEnhance;

      if (encrypt && type === "All" || type === "Decryption") {
        decryption = NativeEncrypt.Base64ToString(encrypt)
        decryptionMap.set("decryption", decryption)
      }
      if (encryptASCII && (type === "All" || type === "ASCII")) {
        let ASCII = this.ASCIIToText(encryptASCII, encryptASCII.length).toString().replaceAll(',', ''), decryptionASCII = ASCII && NativeEncrypt.Base64ToString(ASCII)
        decryptionMap.set("decryptionASCII", decryptionASCII)
      }
      if (encryptASCII && (type === "All" || type === "DecryptionEnhance")) {
        decryptionEnhance = NativeEncrypt.Base64ToString(this.ASCIIToText(encryptASCII, encryptASCII.length).toString().replaceAll(',', ''));
        decryptionMap.set("decryptionEnhance", decryptionEnhance)
      }
      return decryptionMap

    } catch (e) {
      throw Error('解码出错')
    }
  }
}



// let dd = NativeEncrypt.encryptTobase64({ name: 'selfsummer', sex: '男' })
// console.log('加密数据', dd);
// console.log('解码数据', NativeEncrypt.decryptionWithBase64(dd));

/**
 * 使用 crypto-js 加密，同时继承了原生加密
 */
export class EncryptionToDecrypt extends NativeEncrypt {
  public readonly key?: string | number
  constructor(key?: string | number) {
    super()
    this.key = key
  }

  /**
 * 加密设置
 * @param data 设置加密参数
 * @returns String
 */
  static encryptionCryptoJS = (data: encryptionData) => AES.encrypt(JSON.stringify(data), new runtime().Envet.systenKey).toString();


  /**
 * 解密
 * @param data 
 * @returns 返回解密后的数据
 */
  static decryptionCryptoJS = (data: string) => AES.decrypt(data, new runtime().Envet.systenKey).toString(enc.Utf8);


}


// /**
//  * 加密设置
//  * @param data 设置加密参数
//  * @returns String
//  */
// export const encryptionCryptoJS = (data: encryptionData) => AES.encrypt(JSON.stringify(data), new runtime().Envet.systenKey).toString();
// /**
//  * 解密
//  * @param data 
//  * @returns 返回解密后的数据
//  */
// export const decryptionCryptoJS = (data: string) => AES.decrypt(data, new runtime().Envet.systenKey).toString(enc.Utf8);

// const objectSwitchString = (setObj: Object | string): object | string => {
//   if (isType(setObj) !== 'Object') return setObj;
//   return JSON.stringify(setObj);
// }


// export const encryptTobase64 = (data: any): string => {
//   if (isType(data) === 'Object') {
//     let set = encodeURIComponent(objectSwitchString(data) as string), result = btoa(set);
//     return result
//   } else {
//     let set = encodeURIComponent(data), result = btoa(set);
//     return result;
//   }
// }
// /**
//  * 解码数据
//  * @param {any} data 数据
//  */
// export const decryptionWithBase64 = (data: string) => {
//   try {
//     let jieMi = atob(data), jieM = decodeURIComponent(jieMi);
//     return jieM;
//   } catch (e) {
//     throw Error('解码出错')
//   }
// }




